package com.tanhua.manage.service;


import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.domain.vo.CountVo;
import com.tanhua.manage.domain.AnalysisByDay;
import com.tanhua.manage.mapper.AnalysisByDayMapper;
import com.tanhua.manage.mapper.LogMapper;
import com.tanhua.manage.utils.ComputeUtil;
import com.tanhua.manage.vo.AnalysisSummaryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class AnalysisByDayService extends ServiceImpl<AnalysisByDayMapper, AnalysisByDay> {

    @Autowired
    private LogMapper logMapper;

    /**
     * 接口名称：概要统计信息
     */
    public ResponseEntity<Object> summary() {
        // 1.查询累计新增用户数，select sum(num_registered) as num_registered from tb_analysis_by_day
        AnalysisByDay analysisByDay = query().select("sum(num_registered) as num_registered").one();
        Integer numRegistered = analysisByDay.getNumRegistered();

        // 2.查询今日新增、活跃数、登录数，select * from tb_analysis_by_day where record_date = '2021-03-06'
        Date date = new Date();
        String now = new SimpleDateFormat("yyyy-MM-dd").format(date);
        AnalysisByDay recordToday = query().eq("record_date", now).one();
        // 今日新增用户数
        Integer numRegisteredToday = recordToday.getNumRegistered();
        // 今日活跃数
        Integer numActiveToday = recordToday.getNumActive();
        // 今日登录数
        Integer numLoginToday = recordToday.getNumLogin();

        // 3.查询昨日新增、活跃数、登录数
        AnalysisByDay recordYes = query().eq("record_date", ComputeUtil.offsetDay(date, -1)).one();
        // 昨日新增用户数
        Integer numRegisteredYes = recordYes.getNumRegistered();
        // 昨日活跃数
        Integer numActiveYes = recordYes.getNumActive();
        // 昨日登录数
        Integer numLoginYes = recordYes.getNumLogin();

        // 4.查询过去7天活跃、过去30天活跃
        Long day7 = this.getBaseMapper().findNumActiveByDate(ComputeUtil.offsetDay(date, -7), now);
        Long day30 = this.getBaseMapper().findNumActiveByDate(ComputeUtil.offsetDay(date, -30), now);

        // 5.封装返回数据
        AnalysisSummaryVo vo = new AnalysisSummaryVo();
        vo.setCumulativeUsers(numRegistered.longValue());
        vo.setActivePassMonth(day30);
        vo.setActivePassWeek(day7);
        vo.setNewUsersToday(numRegisteredToday.longValue());
        vo.setNewUsersTodayRate(ComputeUtil.computeRate(numRegisteredToday, numRegisteredYes));
        vo.setLoginTimesToday(numLoginToday.longValue());
        vo.setLoginTimesTodayRate(ComputeUtil.computeRate(numLoginToday, numLoginYes));
        vo.setActiveUsersToday(numActiveToday.longValue());
        vo.setActiveUsersTodayRate(ComputeUtil.computeRate(numActiveToday, numActiveYes));

        return ResponseEntity.ok(vo);
    }

    /**
     * 统计，查询日志表数据，更新统计日表中
     */
    public void anasysis() {
        // 1.查询今天的统计数据
        // 获取当天的日期，并格式化
        Date date = new Date();
        String now = new SimpleDateFormat("yyyy-MM-dd").format(date);

        // 查询新增用户数
        Long numResister = logMapper.queryNumsByType(now, "0102");
        // 查询登录次数
        Long numLogin = logMapper.queryNumsByType(now, "0101");
        // 查询活跃用户数
        Long numActive = logMapper.queryNumsByDate(now);
        // 查询次日留存数
        Long numRetention1d = logMapper.queryRetention1d(now, ComputeUtil.offsetDay(date, -1));

        // 2.查询统计日表，判断当天的数据是否存在
        AnalysisByDay recordToday = this.query().eq("record_date", now).one();

        if (recordToday == null) {

            AnalysisByDay analysisByDay = new AnalysisByDay();
            // 数据库存储的日期必须是年月日格式
            analysisByDay.setRecordDate(DateUtil.parseDate(now));
            analysisByDay.setNumRegistered(numResister.intValue());
            analysisByDay.setNumActive(numActive.intValue());
            analysisByDay.setNumLogin(numLogin.intValue());
            analysisByDay.setNumRetention1d(numRetention1d.intValue());
            analysisByDay.setCreated(new Date());
            analysisByDay.setUpdated(new Date());

            // 新增
            save(analysisByDay);

        } else {
            // 更新
            recordToday.setNumRegistered(numResister.intValue());
            recordToday.setNumActive(numActive.intValue());
            recordToday.setNumLogin(numLogin.intValue());
            recordToday.setNumRetention1d(numRetention1d.intValue());
            recordToday.setUpdated(new Date());

            updateById(recordToday);
        }
    }

    /**
     * 接口名称：新增、活跃用户、次日留存
     */
    //101 新增 102 活跃用户 103 次日留存率
    public ResponseEntity<Object> users(Long sd, Long ed, Integer type) throws ParseException {
        //转换开始时间
        String sdTime = new SimpleDateFormat("yyyy-MM-dd").format(sd);
        //转换结束时间
        String edTime = new SimpleDateFormat("yyyy-MM-dd").format(ed);

        //截取年份
        String Year = sdTime.split("-")[0];
        //获取去年的时间
        String lastSdTime = Integer.valueOf(Year) - 1 + "-" + sdTime.split("-")[1] + "-" + sdTime.split("-")[2];
        String lastEdTime = Integer.valueOf(Year) - 1 + "-" + edTime.split("-")[1] + "-" + edTime.split("-")[2];

        //今年
        List<AnalysisByDay> analysisByDayList = this.getBaseMapper().getAnalysisByDay(sdTime, edTime);
        //去年
        List<AnalysisByDay> analysisByDayListLastYear = this.getBaseMapper().getAnalysisByDay(lastSdTime, lastEdTime);
        List<CountVo> countVos=new ArrayList<>();
        if(analysisByDayList!=null){
            for (AnalysisByDay analysisByDay : analysisByDayList) {
                if(type==101){
                    CountVo countVo = new CountVo();
                    countVo.setTitle(analysisByDay.getRecordDate().toString());
                    countVo.setAmount(analysisByDay.getNumRegistered());
                    countVos.add(countVo);
                }else if(type==102){
                    CountVo countVo = new CountVo();
                    countVo.setTitle(analysisByDay.getRecordDate().toString());
                    countVo.setAmount(analysisByDay.getNumActive());
                    countVos.add(countVo);
                }else {
                    CountVo countVo = new CountVo();
                    countVo.setTitle(analysisByDay.getRecordDate().toString());
                    countVo.setAmount(analysisByDay.getNumRetention1d());
                    countVos.add(countVo);
                }
            }
        }

        List<CountVo> lastCountVos=new ArrayList<>();
        if(analysisByDayListLastYear!=null){
            for (AnalysisByDay analysisByDay : analysisByDayListLastYear) {
                if(type==101){
                    CountVo countVo = new CountVo();
                    countVo.setTitle(analysisByDay.getRecordDate().toString());
                    countVo.setAmount(analysisByDay.getNumRegistered());
                    lastCountVos.add(countVo);
                }else if(type==102){
                    CountVo countVo = new CountVo();
                    countVo.setTitle(analysisByDay.getRecordDate().toString());
                    countVo.setAmount(analysisByDay.getNumActive());
                    lastCountVos.add(countVo);
                }else {
                    CountVo countVo = new CountVo();
                    countVo.setTitle(analysisByDay.getRecordDate().toString());
                    countVo.setAmount(analysisByDay.getNumRetention1d());
                    lastCountVos.add(countVo);
                }
            }
        }

        Object[] laYear = lastCountVos.toArray(new Object[]{});
        Object[] thisYear = countVos.toArray(new Object[]{});
        Object[] lastYear=new Object[thisYear.length];
        for (int i = 0; i < lastYear.length; i++) {
            CountVo countVo=new CountVo();
            countVo.setAmount(0);
            for (int j = 0; j < laYear.length; j++) {
                CountVo countVo1= (CountVo) laYear[j];
                CountVo countVo2= (CountVo) thisYear[i];

                SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US);
                Date date = sdf.parse(countVo1.getTitle());

                String dateStr1 = new SimpleDateFormat("MM-dd").format(date);
                Date date2 = sdf.parse(countVo2.getTitle());
                String dateStr2 = new SimpleDateFormat("MM-dd").format(date2);
                if(dateStr1.equals(dateStr2)){
                    countVo=countVo1;
                }
            }
            lastYear[i]=countVo;
        }
        Map<String, Object> map=new HashMap<>();
        map.put("thisYear",thisYear);
        map.put("lastYear",lastYear);
        return ResponseEntity.ok(JSON.toJSONString(map));
    }
}
